package menus;
import gui.CustomTable;
import gui.CustomTableModel;
import gui.ExceptionListener;
import gui.MainView;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.plaf.basic.BasicInternalFrameTitlePane.MaximizeAction;

import database.CustData;
import database.ManagerData;
import database.PosData;

import java.sql.*;
import java.text.*;

public class PosMenu extends MenuSuperclass implements ActionListener, ExceptionListener
{
	private PosData transaction = null;
	private ManagerData items = null;
	private String recString = null;
	private String retString = null;

	public PosMenu(MainView mv)
	{
		this.mv = mv;
		// need this for receipt numbers
		transaction = new PosData();
		transaction.addExceptionListener(this);
		// need this to adjust inventory
		items = new ManagerData();
		items.addExceptionListener(this);
	}


	// methods called by different menu items... np = new purchase, cp = continue purchase, etc.
	public void actionPerformed(ActionEvent e)
	{
		String actionCommand = e.getActionCommand();

		// why don't these pop-ups always instantiate?
		if (actionCommand.equals("np"))
		{
			// new purchase needs new rec# and an entry in the purchase table before items can be added
			// should this be rolled back if purchase is zero items or is cancelled? (yes but don't bother)
			int recNum = transaction.getMaxReceipt();

			System.out.println("stock upc 1 before purchase: " + transaction.showStock(1));

			if (transaction.isPurDateNull(recNum)) {
				mv.updateStatusBar("Finish last purchase first.");
				message("Finish last purchase first.", mv.georgeIcon);
				showTransaction(recNum);
			} else {
				recNum++;
				// show items already in transaction (blank)
				showTransaction(recNum);
				mv.updateStatusBar("Purchase #"+recNum+" started...");
				// add entry to purchase db
				transaction.addPurchase(recNum);
				// set receipt # for transaction form
				recString = String.valueOf(recNum);
				TransactionDialog iDialog = new TransactionDialog(mv);
				iDialog.pack();
				mv.centerWindow(iDialog);
				iDialog.setVisible(true);
				return;
			}
		}

		if (actionCommand.equals("cp"))
		{
			int recNum = transaction.getMaxReceipt();
			if (transaction.isPurDateNull(recNum)) {
				// continue purchase looks up last rec# to add more items
				// concurrent usage of db would need this value cached per terminal
				// show items already in transaction
				showTransaction(recNum);
				// set receipt # for transaction form
				recString = String.valueOf(recNum);
				TransactionDialog iDialog = new TransactionDialog(mv);
				iDialog.pack();
				mv.centerWindow(iDialog);
				iDialog.setVisible(true);
				return;
			} else {
				mv.updateStatusBar("No open purchases.");
				message("No open purchases.", mv.georgeIcon);

			}
		}

		if (actionCommand.equals("fp"))
		{
			int recNum = transaction.getMaxReceipt();
			// is purchase open?
			if (transaction.isPurDateNull(recNum)) {

				// show a subtotal
				message("Total Purchase", "$"+transaction.getTotalPurchase(recNum));


				FinishPurchaseDialog iDialog = new FinishPurchaseDialog(mv);
				iDialog.pack();
				mv.centerWindow(iDialog);
				iDialog.setVisible(true);

			} else {
				mv.updateStatusBar("No open purchases.");
				message("No open purchases.", mv.georgeIcon);

			}
			
			System.out.println("upc 1 stock after purchase: " + transaction.showStock(1));
		}

		// reverse of above methods with more checks
		if (actionCommand.equals("nr"))
		{

			System.out.println("upc 1 stock before return: " + transaction.showStock(1));
			
			int retId = transaction.getMaxRetId();

			if (transaction.isRetDateNull(retId)) {
				mv.updateStatusBar("Finish last return first.");
				message("Finish last return first.", mv.georgeIcon);
				showReturn(retId);
			} else {
				retId++;
				// show items already in return transaction (blank)
				showReturn(retId);

				// set return # for Return form
				retString = String.valueOf(retId);
				ReturnDialog iDialog = new ReturnDialog(mv);
				iDialog.pack();
				mv.centerWindow(iDialog);
				iDialog.setVisible(true);

				return;
			}
		}
		if (actionCommand.equals("cr"))
		{
			int retId = transaction.getMaxRetId();

			if (transaction.isRetDateNull(retId)) {
				// continue return looks up last ret# to add more items
				// concurrent usage of db would need this value cached per terminal
				// show items already in transaction
				showReturn(retId);
				// set return # for transaction form
				retString = String.valueOf(retId);
				ContinueReturnDialog iDialog = new ContinueReturnDialog(mv);
				iDialog.pack();
				mv.centerWindow(iDialog);
				iDialog.setVisible(true);
				return;
			} else {
				mv.updateStatusBar("No open returns.");
				message("No open returns.", mv.georgeIcon);

			}
		}


		if (actionCommand.equals("fr"))
		{
			int retId = transaction.getMaxRetId();
			// is purchase open?
			if (transaction.isRetDateNull(retId)) {
				// then set return date to indicate return is closed
				transaction.setRetDate(retId);
				mv.updateStatusBar("Return #"+retId+" finished.");
				transaction.updatePurchase(retId);
				//System.out.println("called Up");
				// debit inventory
				transaction.updateStockOnReturn(retId);
				// show a subtotal for refund
				message("Total Refund", "$"+transaction.getTotalReturn(retId));

				// clear table
				System.out.println("upc 1 stock after return: " + transaction.showStock(1));

				return;
			} else {
				mv.updateStatusBar("No open returns.");
				message("No open returns.", mv.georgeIcon);

			}
		}
	}

	private void showTransaction(int rec)
	{
		ResultSet rs = transaction.showTransaction(rec);
		CustomTableModel model = new CustomTableModel(transaction.getConnection(), rs);
		CustomTable data = new CustomTable(model);
		model.addExceptionListener(this);
		data.addExceptionListener(this);
		mv.addTable(data);
	}

	private void showReturn(int retId)
	{
		ResultSet rs = transaction.showReturn(retId);
		CustomTableModel model = new CustomTableModel(transaction.getConnection(), rs);
		CustomTable data = new CustomTable(model);
		model.addExceptionListener(this);
		data.addExceptionListener(this);
		mv.addTable(data);
	}


	class TransactionDialog extends JDialog implements ActionListener
	{
		private JTextField upcField = new JTextField(15);
		private JTextField qtyField = new JTextField(15);

		public TransactionDialog(JFrame parent)

		{
			super(parent, "Purchase/Return Item", true);
			setResizable(false);
			JPanel contentPane = new JPanel(new BorderLayout());
			setContentPane(contentPane);
			contentPane.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
			JPanel inputPane = new JPanel();
			String title = "Purchase #"+recString;
			inputPane.setBorder(BorderFactory.createCompoundBorder(
					new TitledBorder(new EtchedBorder(), title),
					new EmptyBorder(5, 5, 5, 5)));
			GridBagLayout gb = new GridBagLayout();
			GridBagConstraints c = new GridBagConstraints();
			inputPane.setLayout(gb);

			JLabel label = new JLabel("UPC: ", SwingConstants.RIGHT);
			c.gridwidth = GridBagConstraints.RELATIVE;
			c.insets = new Insets(5, 0, 0, 5);
			c.anchor = GridBagConstraints.EAST;
			gb.setConstraints(label, c);
			inputPane.add(label);
			c.gridwidth = GridBagConstraints.REMAINDER;
			c.insets = new Insets(5, 0, 0, 0);
			c.anchor = GridBagConstraints.WEST;
			gb.setConstraints(upcField, c);
			inputPane.add(upcField);

			label = new JLabel("Quantity: ", SwingConstants.RIGHT);
			c.gridwidth = GridBagConstraints.RELATIVE;
			c.insets = new Insets(5, 0, 0, 5);
			c.anchor = GridBagConstraints.EAST;
			gb.setConstraints(label, c);
			inputPane.add(label);
			c.gridwidth = GridBagConstraints.REMAINDER;
			c.insets = new Insets(5, 0, 0, 0);
			c.anchor = GridBagConstraints.WEST;
			gb.setConstraints(qtyField, c);
			inputPane.add(qtyField);

			// set last field action command for enter key
			qtyField.addActionListener(this);
			qtyField.setActionCommand("OK");

			// ok/cancel button pane
			JPanel buttonPane = new JPanel();
			buttonPane.setLayout(new BoxLayout(buttonPane, BoxLayout.X_AXIS));
			buttonPane.setBorder(BorderFactory.createEmptyBorder(10, 0, 0, 2));
			JButton OKButton = new JButton("OK");
			JButton cancelButton = new JButton("Cancel");
			OKButton.addActionListener(this);
			OKButton.setActionCommand("OK");
			cancelButton.addActionListener(new ActionListener()
			{
				public void actionPerformed(ActionEvent e)
				{
					dispose();
				}
			});
			buttonPane.add(Box.createHorizontalGlue());
			buttonPane.add(OKButton);
			buttonPane.add(Box.createRigidArea(new Dimension(10,0)));
			buttonPane.add(cancelButton);
			contentPane.add(inputPane, BorderLayout.CENTER);
			contentPane.add(buttonPane, BorderLayout.SOUTH);
			addWindowListener(new WindowAdapter()
			{
				public void windowClosing(WindowEvent e)
				{
					dispose();
				}
			});
		}


		public void actionPerformed(ActionEvent e)
		{
			String actionCommand = e.getActionCommand();
			if (actionCommand.equals("OK"))
			{
				if (validateInsert() != VALIDATIONERROR)
				{
					dispose();
				}
				else
				{
					Toolkit.getDefaultToolkit().beep();
					JOptionPane errorPopup = new JOptionPane();
					errorPopup.showMessageDialog(this, "Invalid Input",
							"Error", JOptionPane.ERROR_MESSAGE);
				}
			}

		}

		private int validateInsert()
		{
			Integer rec = Integer.valueOf(recString);
			Integer upc = Integer.valueOf(upcField.getText().trim());
			Integer qty = Integer.valueOf(qtyField.getText().trim());
			
			//CustData cd = new CustData();

			if (transaction.findReceiptAndUPC(rec, upc) && transaction.getStock(upc) >= qty) {
				mv.updateStatusBar("That UPC already exists... adjusted quantity.");
				transaction.adjustPurItem(rec, upc, qty);
				showTransaction(rec);
				return OPERATIONSUCCESS;

			}

			

			if (transaction.getStock(upc) >= (qty)) {
				mv.updateStatusBar("Added UPC #"+upc+" to Purchase #"+rec+".");
				transaction.addPurItem(rec, upc, qty);
			} else{
				message("You selected too much quantity! Select " + transaction.getStock(upc) + " quantity or lower!", mv.georgeIcon);
			}

			showTransaction(rec);
			return OPERATIONSUCCESS;
		}
	}

	class ReturnDialog extends JDialog implements ActionListener
	{
		private JTextField recField = new JTextField(15);
		private JTextField upcField = new JTextField(15);
		private JTextField qtyField = new JTextField(15);

		public ReturnDialog(JFrame parent)

		{
			super(parent, "Purchase/Return Item", true);
			setResizable(false);
			JPanel contentPane = new JPanel(new BorderLayout());
			setContentPane(contentPane);
			contentPane.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
			JPanel inputPane = new JPanel();
			String title = "Return #"+retString;
			inputPane.setBorder(BorderFactory.createCompoundBorder(
					new TitledBorder(new EtchedBorder(), title),
					new EmptyBorder(5, 5, 5, 5)));
			GridBagLayout gb = new GridBagLayout();
			GridBagConstraints c = new GridBagConstraints();
			inputPane.setLayout(gb);

			JLabel label = new JLabel("Receipt #: ", SwingConstants.RIGHT);
			c.gridwidth = GridBagConstraints.RELATIVE;
			c.insets = new Insets(5, 0, 0, 5);
			c.anchor = GridBagConstraints.EAST;
			gb.setConstraints(label, c);
			inputPane.add(label);
			c.gridwidth = GridBagConstraints.REMAINDER;
			c.insets = new Insets(5, 0, 0, 0);
			c.anchor = GridBagConstraints.WEST;
			gb.setConstraints(recField, c);
			inputPane.add(recField);

			label = new JLabel("UPC: ", SwingConstants.RIGHT);
			c.gridwidth = GridBagConstraints.RELATIVE;
			c.insets = new Insets(5, 0, 0, 5);
			c.anchor = GridBagConstraints.EAST;
			gb.setConstraints(label, c);
			inputPane.add(label);
			c.gridwidth = GridBagConstraints.REMAINDER;
			c.insets = new Insets(5, 0, 0, 0);
			c.anchor = GridBagConstraints.WEST;
			gb.setConstraints(upcField, c);
			inputPane.add(upcField);

			label = new JLabel("Quantity: ", SwingConstants.RIGHT);
			c.gridwidth = GridBagConstraints.RELATIVE;
			c.insets = new Insets(5, 0, 0, 5);
			c.anchor = GridBagConstraints.EAST;
			gb.setConstraints(label, c);
			inputPane.add(label);
			c.gridwidth = GridBagConstraints.REMAINDER;
			c.insets = new Insets(5, 0, 0, 0);
			c.anchor = GridBagConstraints.WEST;
			gb.setConstraints(qtyField, c);
			inputPane.add(qtyField);

			// set last field action command for enter key
			qtyField.addActionListener(this);
			qtyField.setActionCommand("OK");

			// ok/cancel button pane
			JPanel buttonPane = new JPanel();
			buttonPane.setLayout(new BoxLayout(buttonPane, BoxLayout.X_AXIS));
			buttonPane.setBorder(BorderFactory.createEmptyBorder(10, 0, 0, 2));
			JButton OKButton = new JButton("OK");
			JButton cancelButton = new JButton("Cancel");
			OKButton.addActionListener(this);
			OKButton.setActionCommand("OK");
			cancelButton.addActionListener(new ActionListener()
			{
				public void actionPerformed(ActionEvent e)
				{
					dispose();
				}
			});
			buttonPane.add(Box.createHorizontalGlue());
			buttonPane.add(OKButton);
			buttonPane.add(Box.createRigidArea(new Dimension(10,0)));
			buttonPane.add(cancelButton);
			contentPane.add(inputPane, BorderLayout.CENTER);
			contentPane.add(buttonPane, BorderLayout.SOUTH);
			addWindowListener(new WindowAdapter()
			{
				public void windowClosing(WindowEvent e)
				{
					dispose();
				}
			});
		}


		public void actionPerformed(ActionEvent e)
		{
			String actionCommand = e.getActionCommand();
			if (actionCommand.equals("OK"))
			{
				if (validateInsert() != VALIDATIONERROR)
				{
					dispose();
				}
				else
				{
					Toolkit.getDefaultToolkit().beep();
					JOptionPane errorPopup = new JOptionPane();
					errorPopup.showMessageDialog(this, "Invalid Input",
							"Error", JOptionPane.ERROR_MESSAGE);
				}
			}

		}

		private int validateInsert()
		{
			Integer ret = Integer.valueOf(retString);
			Integer upc = Integer.valueOf(upcField.getText().trim());
			Integer qty = Integer.valueOf(qtyField.getText().trim());
			Integer rec = Integer.valueOf(recField.getText().trim());
			Date purDate = transaction.getPurDate(rec);
			Date date = transaction.date();

			if (transaction.isRecValid(rec) && transaction.daysBetween(purDate, date) <= 15) {
				

				if (transaction.hasItemAndQty(rec, upc, qty)) {
					mv.updateStatusBar("Return #"+ret+" started...");
					transaction.addReturn(ret, rec);
					mv.updateStatusBar("Added UPC #"+upc+" to Return #"+ret+".");
					transaction.addRetItem(ret, upc, qty);
				} else {
					message("You selected too much quantity! Select " + transaction.getPurQuantity(rec, upc) + " quantity or lower!", mv.georgeIcon);
					return OPERATIONFAILED;
				}

				showReturn(ret);
				return OPERATIONSUCCESS;

			} else {
				if (transaction.isRecValid(rec)) {
					message("It has been more than 15 days!", mv.georgeIcon);
					return OPERATIONFAILED;
				} else {
					message("Not a valid receipt number!" , mv.georgeIcon);
					return OPERATIONFAILED;
				}

			}
		}
	}

	class ContinueReturnDialog extends JDialog implements ActionListener
	{
		private JTextField qtyField = new JTextField(15);

		public ContinueReturnDialog(JFrame parent)

		{
			super(parent, "Purchase/Return Item", true);
			setResizable(false);
			JPanel contentPane = new JPanel(new BorderLayout());
			setContentPane(contentPane);
			contentPane.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
			JPanel inputPane = new JPanel();
			String title = "Return #"+retString;
			inputPane.setBorder(BorderFactory.createCompoundBorder(
					new TitledBorder(new EtchedBorder(), title),
					new EmptyBorder(5, 5, 5, 5)));
			GridBagLayout gb = new GridBagLayout();
			GridBagConstraints c = new GridBagConstraints();
			inputPane.setLayout(gb);

			JLabel label = new JLabel("Quantity: ", SwingConstants.RIGHT);
			c.gridwidth = GridBagConstraints.RELATIVE;
			c.insets = new Insets(5, 0, 0, 5);
			c.anchor = GridBagConstraints.EAST;
			gb.setConstraints(label, c);
			inputPane.add(label);
			c.gridwidth = GridBagConstraints.REMAINDER;
			c.insets = new Insets(5, 0, 0, 0);
			c.anchor = GridBagConstraints.WEST;
			gb.setConstraints(qtyField, c);
			inputPane.add(qtyField);

			// set last field action command for enter key
			qtyField.addActionListener(this);
			qtyField.setActionCommand("OK");

			// ok/cancel button pane
			JPanel buttonPane = new JPanel();
			buttonPane.setLayout(new BoxLayout(buttonPane, BoxLayout.X_AXIS));
			buttonPane.setBorder(BorderFactory.createEmptyBorder(10, 0, 0, 2));
			JButton OKButton = new JButton("OK");
			JButton cancelButton = new JButton("Cancel");
			OKButton.addActionListener(this);
			OKButton.setActionCommand("OK");
			cancelButton.addActionListener(new ActionListener()
			{
				public void actionPerformed(ActionEvent e)
				{
					dispose();
				}
			});
			buttonPane.add(Box.createHorizontalGlue());
			buttonPane.add(OKButton);
			buttonPane.add(Box.createRigidArea(new Dimension(10,0)));
			buttonPane.add(cancelButton);
			contentPane.add(inputPane, BorderLayout.CENTER);
			contentPane.add(buttonPane, BorderLayout.SOUTH);
			addWindowListener(new WindowAdapter()
			{
				public void windowClosing(WindowEvent e)
				{
					dispose();
				}
			});
		}


		public void actionPerformed(ActionEvent e)
		{
			String actionCommand = e.getActionCommand();
			if (actionCommand.equals("OK"))
			{
				if (validateInsert() != VALIDATIONERROR)
				{
					dispose();
				}
				else
				{
					Toolkit.getDefaultToolkit().beep();
					JOptionPane errorPopup = new JOptionPane();
					errorPopup.showMessageDialog(this, "Invalid Input",
							"Error", JOptionPane.ERROR_MESSAGE);
				}
			}

		}

		private int validateInsert()
		{
			Integer ret = Integer.valueOf(retString);
			Integer qty = Integer.valueOf(qtyField.getText().trim());
			int upc = transaction.getRetUpc(ret);
			int rec = transaction.getRec(ret);

			//qty = qty + transaction.getRetQuantity(ret);

			if (transaction.findReturnAndUPC(ret, upc) && transaction.hasItemAndQty(rec, upc, qty)) {
				mv.updateStatusBar("That UPC already exists ...adjusting quantity");
				transaction.adjustRetItem(ret, upc, qty);
				showReturn(ret);
				return OPERATIONSUCCESS;
			}	else {
				if (transaction.findReturnAndUPC(ret, upc)) {
					message("You selected too much quantity! Select " + transaction.getPurQuantity(rec, upc) + " quantity or lower!", mv.georgeIcon);
				} else {
					if (transaction.hasItemAndQty(rec, upc, qty)) {
						message("Not a valid return!", mv.georgeIcon);
					}
				}
			}

			return OPERATIONFAILED;

		}
	}

	class FinishPurchaseDialog extends JDialog implements ActionListener
	{
		private JTextField cardField = new JTextField(16);

		public FinishPurchaseDialog(JFrame parent)

		{
			super(parent, "Purchase/Return Item", true);
			setResizable(false);
			JPanel contentPane = new JPanel(new BorderLayout());
			setContentPane(contentPane);
			contentPane.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
			JPanel inputPane = new JPanel();
			String title = "Purchase #"+recString;
			inputPane.setBorder(BorderFactory.createCompoundBorder(
					new TitledBorder(new EtchedBorder(), title),
					new EmptyBorder(5, 5, 5, 5)));
			GridBagLayout gb = new GridBagLayout();
			GridBagConstraints c = new GridBagConstraints();
			inputPane.setLayout(gb);

			JLabel label = new JLabel("Credit Card #: ", SwingConstants.RIGHT);
			c.gridwidth = GridBagConstraints.RELATIVE;
			c.insets = new Insets(5, 0, 0, 5);
			c.anchor = GridBagConstraints.EAST;
			gb.setConstraints(label, c);
			inputPane.add(label);
			c.gridwidth = GridBagConstraints.REMAINDER;
			c.insets = new Insets(5, 0, 0, 0);
			c.anchor = GridBagConstraints.WEST;
			gb.setConstraints(cardField, c);
			inputPane.add(cardField);

			// set last field action command for enter key
			cardField.addActionListener(this);
			cardField.setActionCommand("Card");

			// ok/cancel button pane
			JPanel buttonPane = new JPanel();
			buttonPane.setLayout(new BoxLayout(buttonPane, BoxLayout.X_AXIS));
			buttonPane.setBorder(BorderFactory.createEmptyBorder(10, 0, 0, 2));
			JButton cardButton = new JButton("Card");
			JButton cashButton = new JButton("Cash");
			cardButton.addActionListener(this);
			cardButton.setActionCommand("Card");
			cashButton.addActionListener(new ActionListener()
			{
				public void actionPerformed(ActionEvent e)
				{
					message(transaction.printReceipt(transaction.getMaxReceipt()), mv.georgeIcon);

					transaction.setPurDate(transaction.getMaxReceipt());
					// then set purchase date to indicate purchase is closed
					mv.updateStatusBar("Purchase #"+transaction.getMaxReceipt()+" finished.");
					// debit inventory
					transaction.updateStockOnPurchase(transaction.getMaxReceipt());

					dispose();
				}
			});
			buttonPane.add(Box.createHorizontalGlue());
			buttonPane.add(cardButton);
			buttonPane.add(Box.createRigidArea(new Dimension(10,0)));
			buttonPane.add(cashButton);
			contentPane.add(inputPane, BorderLayout.CENTER);
			contentPane.add(buttonPane, BorderLayout.SOUTH);
			addWindowListener(new WindowAdapter()
			{
				public void windowClosing(WindowEvent e)
				{
					dispose();
				}
			});
		}


		public void actionPerformed(ActionEvent e)
		{
			String actionCommand = e.getActionCommand();
			if (actionCommand.equals("Card"))
			{
				if (validateInsert() != VALIDATIONERROR)
				{
					dispose();
				}
				else
				{
					Toolkit.getDefaultToolkit().beep();
					JOptionPane errorPopup = new JOptionPane();
					errorPopup.showMessageDialog(this, "Invalid Input",
							"Error", JOptionPane.ERROR_MESSAGE);
				}
			}

		}

		private int validateInsert()
		{
			if (Integer.valueOf(cardField.getText().trim().length()) == 16) {
				String cardNum = cardField.getText().substring(11, 15).trim();
				String receipt = transaction.printReceipt(transaction.getMaxReceipt()) +
						"Credit Card #: xxxx-xxxx-xxx-" + cardNum;

				message(receipt, mv.georgeIcon);
				transaction.setPurDate(transaction.getMaxReceipt());
				// then set purchase date to indicate purchase is closed
				mv.updateStatusBar("Purchase #"+transaction.getMaxReceipt()+" finished.");
				// debit inventory
				transaction.updateStockOnPurchase(transaction.getMaxReceipt());
				return 0;

			} else {
				message("Not a valid credit card number!", mv.georgeIcon);
				return 1;
			}
		}


	}
}